]> git.r.bdr.sh - rbdr/Flat-Bezel.qsplugin/blame - Flat Bezel/BBObjectCell.m
New icons + fix version
[rbdr/Flat-Bezel.qsplugin] / Flat Bezel / BBObjectCell.m
CommitLineData
768e492e 1#import "BBObjectCell.h"
5200836d
RBR
2
3@implementation BBObjectCell
4
5- (NSCellImagePosition)preferredImagePosition {
6 return NSImageAbove;
7}
8
9- (void)drawWithFrame:(NSRect)cellFrame inView:(NSView *)controlView {
10 BOOL isFirstResponder = [[controlView window] firstResponder] == controlView && ![controlView isKindOfClass:[NSTableView class]];
11 BOOL dropTarget = ([self isHighlighted] && ([self highlightsBy] & NSChangeBackgroundCellMask) && ![self isBezeled]);
12
13 NSColor *fillColor;
14 NSColor *strokeColor = [NSColor clearColor];
15
16 if (isFirstResponder) {
8f25550f 17 fillColor = [NSColor selectedTextBackgroundColor];
5200836d 18 } else {
8f25550f 19 fillColor = [NSColor clearColor];
5200836d
RBR
20 }
21
22 if (dropTarget) {
8f25550f 23 fillColor = [NSColor controlAccentColor];
5200836d
RBR
24 }
25
26 [fillColor setFill];
27 [strokeColor setStroke];
28
29 NSBezierPath *roundRect = [NSBezierPath bezierPath];
80583e8f 30 [roundRect appendBezierPathWithRoundedRectangle:cellFrame withRadius:NSHeight(cellFrame)/cellRadiusFactor];
5200836d
RBR
31 [roundRect fill];
32
33 [self drawInteriorWithFrame:[self drawingRectForBounds:cellFrame] inView:controlView];
34}
35
36- (NSRect)titleRectForBounds:(NSRect)theRect
37{
38 NSRect rect = theRect;
39 rect = NSOffsetRect(rect, 0, -4);
40 return [super titleRectForBounds: rect];
41}
42
43- (void)drawTextForObject:(QSObject *)drawObject withFrame:(NSRect)cellFrame inView:(NSView *)controlView {
44 if ([self imagePosition] == NSImageOnly) return;
45
46 NSString *abbrString = nil;
47 if ([controlView respondsToSelector:@selector(matchedString)])
48 abbrString = [(QSSearchObjectView *)controlView matchedString];
49
50 NSString *nameString = nil;
51 NSIndexSet *hitMask = nil;
52
53 id ranker = [drawObject ranker];
54 if (ranker && abbrString)
55 nameString = [ranker matchedStringForAbbreviation:abbrString hitmask:&hitMask inContext:nil];
56
57 if (!nameString)
58 nameString = [drawObject displayName];
59
60 BOOL rankedStringIsName = [nameString isEqualToString:[drawObject displayName]] || nameString == nil;
61 if (!nameString) {
62 // fall back to the identifier if no reasonable name can be found
63 nameString = [drawObject identifier];
64 }
65 if (!nameString) {
66 // Couldn't find anything sensible to use for the name, fallback to avoid a crash
67 nameString = @"Unknown";
68 }
69
70 BOOL useAlternateColor = [controlView isKindOfClass:[NSTableView class]] && [(NSTableView *)controlView isRowSelected:[(NSTableView *)controlView rowAtPoint:cellFrame.origin]];
71 NSColor *mainColor = (textColor ? textColor : (useAlternateColor ? [NSColor alternateSelectedControlTextColor] : [NSColor controlTextColor]));
72 NSColor *fadedColor = [mainColor colorWithAlphaComponent:0.50];
73 NSRect textDrawRect = [self titleRectForBounds:cellFrame];
74
75 NSMutableAttributedString *titleString = [[[NSMutableAttributedString alloc] initWithString:nameString] autorelease];
76 [titleString setAttributes:rankedStringIsName ? nameAttributes : detailsAttributes range:NSMakeRange(0, [titleString length])];
77
78 // Bring out the matched letters
79 if (abbrString && ![abbrString hasPrefix:@"QSActionMnemonic"]) {
80 [titleString addAttribute:NSForegroundColorAttributeName value:rankedStringIsName ? fadedColor : [fadedColor colorWithAlphaComponent:0.8] range:NSMakeRange(0, [titleString length])];
81
82 NSUInteger i = 0;
83 NSUInteger j = 0;
84 NSUInteger hits[[titleString length]];
85 NSUInteger count = [hitMask getIndexes:(NSUInteger *)&hits maxCount:[titleString length] inIndexRange:nil];
86 NSDictionary *attributes = @{
87 NSForegroundColorAttributeName: rankedStringIsName ? mainColor : fadedColor
88 };
89 for(i = 0; i<count; i += j) {
90 for (j = 1; i+j<count && hits[i+j-1] +1 == hits[i+j]; j++);
91 [titleString addAttributes:attributes range:NSMakeRange(hits[i], j)];
92 }
93 } else {
94 [titleString addAttribute:NSBaselineOffsetAttributeName value:[NSNumber numberWithDouble:-1.0] range:NSMakeRange(0, [titleString length])];
95 }
96//
97// // Ranked string and nameString aren't the same. Show 'nameString ⟷ rankedString' in the UI
98// if (!rankedStringIsName && [drawObject displayName].length) {
99// [titleString addAttribute:NSFontAttributeName value:detailsFont range:NSMakeRange(0,[titleString length])];
100// NSMutableAttributedString *attributedNameString = [[NSMutableAttributedString alloc] initWithString:[drawObject displayName]];
101// [attributedNameString setAttributes:nameAttributes range:NSMakeRange(0, [[drawObject displayName] length])];
102//
103// [attributedNameString appendAttributedString:[[[NSAttributedString alloc] initWithString:@" ⟷ " attributes:rankedNameAttributes] autorelease]];
104// // the replaceCharacters... method inserts the new string into the receiver at the start of the work (range.location and range.length are 0)
105// [titleString replaceCharactersInRange:NSMakeRange(0,0) withAttributedString:attributedNameString];
106// [attributedNameString release];
107// }
108
109 if (showDetails) {
110 NSString *detailsString = [drawObject details];
111
112 NSRange returnRange = [detailsString rangeOfString:@"\n"];
113 if (returnRange.location != NSNotFound) {
114 detailsString = [detailsString substringToIndex:returnRange.location];
115 }
116
117 detailsAttributes = [detailsAttributes mutableCopy];
118 [detailsAttributes setValue:[NSColor grayColor] forKey:NSForegroundColorAttributeName];
119
120 if (detailsString && detailsString.length && ![detailsString isEqualToString:nameString]) {
121 [titleString appendAttributedString:[[[NSAttributedString alloc] initWithString:[NSString stringWithFormat:@"\n%@",detailsString] attributes:detailsAttributes] autorelease]];
122 }
123 }
124
125 NSRect centerRect = rectFromSize([titleString size]);
126 centerRect.size.width = NSWidth(textDrawRect);
127 centerRect.size.height = MIN(NSHeight(textDrawRect), centerRect.size.height);
128 [titleString drawInRect:centerRectInRect(centerRect, textDrawRect)];
129}
130
953623b9
RBR
131- (void)drawSearchPlaceholderWithFrame:(NSRect)cellFrame inView:(NSView *)controlView {
132 NSString *defaultText = NSLocalizedStringWithDefaultValue(@"Type to search", nil, [NSBundle mainBundle], @"Type to search", @"Hint that appears in the first pane of the QS interface when it's empty.");
133 NSSize textSize = [defaultText sizeWithAttributes:nameAttributes];
134 NSRect textRect = centerRectInRect(rectFromSize(textSize), cellFrame);
135 BOOL isFirstResponder = [[controlView window] firstResponder] == controlView && ![controlView isKindOfClass:[NSTableView class]];
136
137 if (isFirstResponder && [controlView isKindOfClass:[QSSearchObjectView class]]) {
138 NSImage *find = [NSImage imageWithSystemSymbolName:@"magnifyingglass.circle.fill" accessibilityDescription:nil];
139
140
141 [find setSize:QSSize16];
142 NSRect findImageRect = expelRectFromRectOnEdge(centerRectInRect(rectFromSize([find size]), cellFrame), textRect, NSRectEdgeMinX, -2);
143
144
145 NSGraphicsContext *graphicsContext = [NSGraphicsContext currentContext];
146 [graphicsContext saveGraphicsState];
147 CGContextRef context = [graphicsContext CGContext];
148 CGContextBeginTransparencyLayerWithRect(context, findImageRect, nil);
149 CGContextSetBlendMode(context, kCGBlendModeNormal);
150 [find drawInRect:findImageRect fromRect:rectFromSize([find size]) operation:NSCompositingOperationSourceOver fraction:1];
151 CGContextSetBlendMode(context, kCGBlendModeSourceIn);
152 CGContextSetFillColorWithColor(context, [[NSColor textColor] CGColor]);
153 CGContextFillRect(context, findImageRect);
154 CGContextEndTransparencyLayer(context);
155
156 [defaultText drawInRect:textRect withAttributes:nameAttributes];
157 }
158}
5200836d 159
80583e8f
RBR
160- (void)drawIconForObject:(QSObject *)object withFrame:(NSRect)cellFrame inView:(NSView *)controlView {
161 NSImage *image = [object icon];
162 NSString *iconName = nil;
163 NSImageSymbolConfiguration *iconConfig = nil;
164 if ([[image name] isEqualToString: @"defaultAction"]) {
165 iconName = @"gearshape.circle";
166 }
167 else if ([[image name] isEqualToString: @"Find"]) {
168 iconName = @"magnifyingglass";
169 }
170 else if ([[image name] isEqualToString: @"Object"]) {
171 iconName = @"cube.transparent";
172 iconConfig = [NSImageSymbolConfiguration configurationWithHierarchicalColor:[NSColor controlAccentColor]];
173 }
174 else if ([[image name] isEqualToString: @"ContactAddress"]) {
175 iconName = @"mappin.circle";
176 }
177 else if ([[image name] isEqualToString: @"ContactEmail"]) {
178 iconName = @"envelope.circle";
179 }
180 else if ([[image name] isEqualToString: @"ContactPhone"]) {
181 iconName = @"phone.circle";
182 }
183 else if ([[image name] isEqualToString: @"DefaultBookmarkIcon"]) {
184 iconName = @"link.circle";
185 }
186 else if ([[image name] isEqualToString: @"Catalog"]) {
187 iconName = @"sparkles.rectangle.stack";
188 }
189 else if ([[image name] isEqualToString: @"Triggers"]) {
190 iconName = @"bolt.fill";
191 }
192
193
194 if (iconName != nil) {
195 NSImage *newIcon = [NSImage imageWithSystemSymbolName:iconName accessibilityDescription:[image name]];
196
197 if (iconConfig == nil) {
198 NSArray *colors = [NSArray arrayWithObjects:[NSColor textColor], [NSColor controlAccentColor], nil];
199 iconConfig = [NSImageSymbolConfiguration configurationWithPaletteColors:colors];
200 }
201
202 QSObject *newObject = [QSObject objectWithName:[object name]];
203 [newObject setIcon:[newIcon imageWithSymbolConfiguration:iconConfig]];
204 [newObject setIconLoaded:[object iconLoaded]];
205 return [super drawIconForObject: newObject withFrame:cellFrame inView:controlView];
206 }
207
208 [super drawIconForObject: object withFrame:cellFrame inView:controlView];
209}
210
953623b9 211@end